package com.homedo.microservice.open.service.gateway.zuul.task;


import com.homedo.common.util.Detect;
import com.homedo.microservice.open.service.gateway.bean.enums.forrouteservice.StatusEnum4RouteService;
import com.homedo.microservice.open.service.gateway.bean.po.Config;
import com.homedo.microservice.open.service.gateway.bean.po.RouteService;
import com.homedo.microservice.open.service.gateway.persistence.dao.ConfigDao;
import com.homedo.microservice.open.service.gateway.service.RouteServiceService;
import com.homedo.microservice.open.service.gateway.zuul.conf.ZuulCommonConf;
import com.homedo.microservice.open.service.gateway.zuul.conf.ZuulDBConf;
import com.netflix.config.ConcurrentCompositeConfiguration;
import com.netflix.config.DynamicPropertyFactory;
import org.joda.time.DateTime;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.util.StopWatch;

import java.util.List;
import java.util.Map;

@Component
public class ZuulCommonConfUpdateTask {
    @Autowired
    private ConfigDao configDao;
    @Autowired
    private ZuulCommonConf zuulCommonConf;
    @Autowired
    private RouteServiceService routeServiceService;

//    private static AbstractConfiguration configFromManager = ConfigurationManager.getConfigInstance();

    private static final Logger LOGGER = LoggerFactory.getLogger(ZuulCommonConfUpdateTask.class);

    @Scheduled(cron = "0/6 * * * * ?")
    public void zuulCommonConfUpdateTask() {
        StopWatch stopWatch = null;
        if (zuulCommonConf.getApplicationLogDetail().get()) {
            stopWatch = new StopWatch();
            stopWatch.start();
            LOGGER.info("更新zull基础配置开始:时间[" + new DateTime().toString("yyyy-MM-dd HH:mm:ss.SSS") + "]");
        }


        this.doSchedule();

        if (zuulCommonConf.getApplicationLogDetail().get()) {
            if (stopWatch != null) {
                stopWatch.stop();
                LOGGER.info("更新zull基础配置结束:时间[" + new DateTime().toString("yyyy-MM-dd HH:mm:ss.SSS") + "],耗时[" + stopWatch.getTotalTimeMillis() + "毫秒]");
            }
        }

    }

    private void doSchedule() {
        List<Config> configs = configDao.getListByApplication(zuulCommonConf.getApplicationName());
        Map<String, String> confs = ZuulDBConf.getInstance().getConfs();

        if (!Detect.notEmpty(configs)) {
            confs.clear();
            return;
        }


        configs.forEach(e -> {
            if (e.getName().equals("ribbon.ReadTimeout")) {
                this.resetServiceHystrixCommandTimeout(e, configs);
            }
            confs.put(e.getName(), e.getValue());
        });

        ConcurrentCompositeConfiguration myConfiguration =
                (ConcurrentCompositeConfiguration) DynamicPropertyFactory.getInstance().getBackingConfigurationSource();

        confs.entrySet().forEach(e -> {
//            configFromManager.setProperty(e.getKey(), e.getValue());// 使用这种方式，放入的属性类型不能动态更新
            myConfiguration.setOverrideProperty(e.getKey(), e.getValue());
        });
    }


    private void resetServiceHystrixCommandTimeout(Config timeoutConfig, List<Config> allConfigs) {
        RouteService routeService = new RouteService();
        routeService.setApplicationName(timeoutConfig.getApplicationName());
        routeService.setStatus((int) StatusEnum4RouteService.EFFECTIVE.getCode());

        List<RouteService> routeServices = routeServiceService.getListByRecord(routeService, null);//获取有效的组列表

        if (!Detect.notEmpty(routeServices)) {
            return;
        }

        ConcurrentCompositeConfiguration myConfiguration =
                (ConcurrentCompositeConfiguration) DynamicPropertyFactory.getInstance().getBackingConfigurationSource();

        try {
            routeServices.forEach(e -> {
                String timeoutkey = "hystrix.command." + e.getId() + ".execution.isolation.thread.timeoutInMilliseconds";
                long readTimeOut = Long.valueOf(timeoutConfig.getValue());
//                long connectTimeout = DynamicPropertyFactory.getInstance().getLongProperty("ribbon.ConnectTimeout", 3000L).get();

                if (!hasSelfSetting(timeoutkey, allConfigs)) {
//                    myConfiguration.setOverrideProperty(timeoutkey, readTimeOut + connectTimeout + 1);
                    myConfiguration.setOverrideProperty(timeoutkey, readTimeOut);//设置成一样，hstrix总超时时间等于ribbon读超时时间，这样能先进入断路器超时配置
                }
            });
        } catch (Exception ex) {
            LOGGER.warn("[设置服务超时时间出错:{}--{}]", timeoutConfig.getValue(), ex.getMessage());
        }
    }

    private boolean hasSelfSetting(String timeoutkey, List<Config> allConfigs) {
        for (Config config : allConfigs) {
            if (config.getName().equals(timeoutkey)) {
                return true;
            }
        }
        return false;
    }


}
